from logging import getLogger
from urllib import quote

from zope import schema
from zope.component import getMultiAdapter
from zope.formlib import form
from zope.interface import implements

from plone.app.portlets.portlets import base
from plone.memoize import ram, instance
from plone.memoize.compress import xhtml_compress
from plone.portlets.interfaces import IPortletDataProvider
from plone.app.portlets.cache import render_cachekey
from plone.app.layout.navigation.root import getNavigationRootObject

from Acquisition import aq_inner
from Products.CMFCore.utils import getToolByName
from Products.CMFPlone import PloneMessageFactory as _

from meercat.ui.plone.browser.portlets.facetBase import BaseFacetRenderer



log = getLogger('meercat.ui.plone.browser.portlets.facetMultiField')

class IFacetMultiFieldPortlet(IPortletDataProvider):
    
    labels = schema.Tuple(title=_(u'Titles'),
                         description=_(u'Displayed titles for the facet, one per '
                                       'line that will be matched with the field. '
                                       'There can be fewer titles than fields, '
                                       'once titles run out, the last one is '
                                       'used for the remaining fields'),
                         required=True,
                         min_length=1)
    
    fields = schema.Tuple(title=_(u'Fields'),
                         description=_(u'The fields (one per line) to facet on.'),
                         required=True,
                         min_length=2)
    
    prefix = schema.TextLine(title=_(u'Prefix'),
                             description=_('Limit facet terms to those with this prefix'),
                             required=False)
    
    limit = schema.Int(title=_(u'Limit'),
                       description=_(u'The default maximum number of facet '
                                     'values to return'),
                       required=False)
    
    mincount = schema.Int(title=_(u'Minimum'),
                          description=_(u'The minimum count for a facet value '
                                        'for it to be displayed.'),
                          required=False)
    
    missing = schema.Bool(title=_(u'Include Missing'),
                          description=_(u'If selected, counts for fields with '
                                        'no value are included. i.e. if there '
                                        'is a facet on subject, it will list '
                                        'off the number of documents matching '
                                        'the query that have no subject'),
                          required=False)
    
    sort = schema.Bool(title=_(u'Sort by value'),
                       description=_(u'If true, terms will be sorted by value '
                                     'instead of by count'),
                       default=True)
    
class Assignment(base.Assignment):
    implements(IFacetMultiFieldPortlet)
    
    def __init__(self, labels, fields, prefix=None, sort=True, limit=None,
                 mincount=None, missing=None):
        self.labels = labels
        self.fields = fields
        self.prefix = prefix
        self.sort = sort
        self.limit = limit
        self.mincount = mincount
        self.missing = missing
    
    @property
    def title(self):
        return _(u"Facet Field: ") + ', '.join(self.fields)

class Renderer(BaseFacetRenderer):
    
    label = None
    field = None
    
    def getTitle(self):
        return self.label
    
    def update(self):
        fq = self.request.get('fq',[])
        if not isinstance(fq,list):
            fq = [fq]
        
        labels = self.data.labels.copy()
        
        if len(labels) < len(self.data.fields):
            for i in range(len(labels),len(self.data.fields)):
                labels.append(self.data.label[-1])
        
        index = 0
        
        for field in self.data.fields:
            match = False
            
            fieldStart = field + ':'
            for filter in fq:
                if filter.startswith(fieldStart):
                    match = True
                    break
            
            if not match:
                break
            
            index += 1
        
        if index == len(self.data.fields):
            index -= 1
        
        self.label = labels[index]
        self.field = self.data.fields[index]
            
        
    
    @instance.memoize
    def getQueryParameters(self):
        params = super(Renderer,self).getQueryParameters()
        
        if not params:
            log.debug('No parameters received from super call')
            return None
        
        params['facet.field'] = self.field
        
        if self.data.prefix:
            params['facet.prefix'] = self.data.prefix
        
        if self.data.limit:
            params['facet.limit'] = self.data.limit
        
        if self.data.mincount:
            params['facet.mincount'] = self.data.mincount
        
        if self.data.sort:
            if aq_inner(self.context).getMeercatManager().getSolrVersion() <= 1.3:
                params['facet.sort'] = 'false'
            else:
                params['facet.sort'] = 'index'
        
        if self.data.missing:
            params['facet.missing'] = 'true'
        
        return params
    
    def getFacets(self):
        facet_counts = self.getFacetCounts()
        
        if not facet_counts:
            log.debug('No facet counts')
            return None
                
        counts = facet_counts.get('facet_fields',{}).get(self.field,{})
        facets = []
        
        for value,count in counts.iteritems():
            facets.append({'value':value,
                           'count':count,
                           'url':self.view.getUrlWithParams(remove=['page'],
                                                            replace=False,
                                                            fq='%s:"%s"' % (self.field,
                                                                            value,))})
        
        if self.data.sort:
            facets.sort(key=lambda f: f['value'].lower())
        else:
            facets.sort(key=lambda f: f['count'], reverse=True)
        
        return facets

class AddForm(base.AddForm):
    form_fields = form.Fields(IFacetMultiFieldPortlet)
    label = _(u"Add Facet Multi-Field Portlet")
    description = _(u"This portlet lists facets for a multi-tiered field from a search.")
    
    def create(self, data):
        return Assignment(label=data.get('label'),
                          field=data.get('field'),
                          prefix=data.get('prefix',None),
                          sort=data.get('sort',None),
                          limit=data.get('limit',None),
                          mincount=data.get('mincount',None),
                          missing=data.get('missing',None))

class EditForm(base.EditForm):
    form_fields = form.Fields(IFacetMultiFieldPortlet)
    label = _(u"Edit Facet Multi-Field Portlet")
    description = AddForm.description
